{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TensorFlow2.0教程-张量极其操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入TensorFlow\n",
    "运行tensorflow程序，需要导入tensorflow模块。\n",
    "从TensorFlow 2.0开始，默认情况下会启用急切执行。 这为TensorFlow提供了一个更加互动的前端节。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import absolute_import, division, print_function\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 Tensors\n",
    "张量是一个多维数组。 与NumPy ndarray对象类似，tf.Tensor对象具有数据类型和形状。 此外，tf.Tensors可以驻留在加速器内存中（如GPU）。 TensorFlow提供了丰富的操作库（tf.add，tf.matmul，tf.linalg.inv等），它们使用和生成tf.Tensors。 这些操作会自动转换原生Python类型，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(3, shape=(), dtype=int32)\n",
      "tf.Tensor([ 5 13], shape=(2,), dtype=int32)\n",
      "tf.Tensor(36, shape=(), dtype=int32)\n",
      "tf.Tensor(24, shape=(), dtype=int32)\n",
      "tf.Tensor(25, shape=(), dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "print(tf.add(1,2))\n",
    "print(tf.add([3,8], [2,5]))\n",
    "print(tf.square(6))\n",
    "print(tf.reduce_sum([7,8,9]))\n",
    "print(tf.square(3)+tf.square(4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "每个Tensor都有形状和类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[ 6]\n",
      " [12]], shape=(2, 1), dtype=int32)\n",
      "(2, 1)\n",
      "<dtype: 'int32'>\n"
     ]
    }
   ],
   "source": [
    "x = tf.matmul([[3], [6]], [[2]])\n",
    "print(x)\n",
    "print(x.shape)\n",
    "print(x.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy数组和tf.Tensors之间最明显的区别是：\n",
    "\n",
    "张量可以由加速器内存（如GPU，TPU）支持。\n",
    "张量是不可变的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy兼容性\n",
    "在TensorFlow tf.Tensors和NumPy ndarray之间转换很容易：\n",
    "\n",
    "TensorFlow操作自动将NumPy ndarrays转换为Tensors。\n",
    "NumPy操作自动将Tensors转换为NumPy ndarrays。\n",
    "使用.numpy（）方法将张量显式转换为NumPy ndarrays。 这些转换通常很容易的，因为如果可能，array和tf.Tensor共享底层内存表示。 但是，共享底层表示并不总是可行的，因为tf.Tensor可以托管在GPU内存中，而NumPy阵列总是由主机内存支持，并且转换涉及从GPU到主机内存的复制。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[36. 36.]\n",
      " [36. 36.]], shape=(2, 2), dtype=float64)\n",
      "[[37. 37.]\n",
      " [37. 37.]]\n",
      "[[36. 36.]\n",
      " [36. 36.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "ndarray = np.ones([2,2])\n",
    "tensor = tf.multiply(ndarray, 36)\n",
    "print(tensor)\n",
    "# 用np.add对tensorflow进行加运算\n",
    "print(np.add(tensor, 1))\n",
    "# 转换为numpy类型\n",
    "print(tensor.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 GPU加速\n",
    "使用GPU进行计算可以加速许多TensorFlow操作。 如果没有任何注释，TensorFlow会自动决定是使用GPU还是CPU进行操作 - 如有必要，可以复制CPU和GPU内存之间的张量。 由操作产生的张量通常由执行操作的设备的存储器支持，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Is GPU availabel:\n",
      "False\n",
      "Is the Tensor on gpu #0:\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "x = tf.random.uniform([3, 3])\n",
    "print('Is GPU availabel:')\n",
    "print(tf.test.is_gpu_available())\n",
    "print('Is the Tensor on gpu #0:')\n",
    "print(x.device.endswith('GPU:0'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**设备名称**\n",
    "\n",
    "Tensor.device属性提供托管张量内容的设备的完全限定字符串名称。 此名称编码许多详细信息，例如正在执行此程序的主机的网络地址的标识符以及该主机中的设备。 这是分布式执行TensorFlow程序所必需的。 如果张量位于主机上的第N个GPU上，则字符串以GPU结尾：<N>。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**显式设备放置(Placement)**\n",
    "\n",
    "在TensorFlow中，放置指的是如何分配（放置）设备以执行各个操作。 如上所述，如果没有提供明确的指导，TensorFlow会自动决定执行操作的设备，并在需要时将张量复制到该设备。 但是，可以使用tf.device上下文管理器将TensorFlow操作显式放置在特定设备上，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "On CPU:\n",
      "10 loops: 1.2e+02ms\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "def time_matmul(x):\n",
    "    start = time.time()\n",
    "    for loop in range(10):\n",
    "        tf.matmul(x, x)\n",
    "    result = time.time() - start\n",
    "    print('10 loops: {:0.2}ms'.format(1000*result))\n",
    "    \n",
    "# 强制使用CPU\n",
    "print('On CPU:')\n",
    "with tf.device('CPU:0'):\n",
    "    x = tf.random.uniform([1000, 1000])\n",
    "    # 使用断言验证当前是否为CPU0\n",
    "    assert x.device.endswith('CPU:0')\n",
    "    time_matmul(x)    \n",
    "\n",
    "# 如果存在GPU,强制使用GPU\n",
    "if tf.test.is_gpu_available():\n",
    "    print('On GPU:')\n",
    "    with tf.device.endswith('GPU:0'):\n",
    "        x = tf.random.uniform([1000, 1000])\n",
    "    # 使用断言验证当前是否为GPU0\n",
    "    assert x.device.endswith('GPU:0')\n",
    "    time_matmul(x)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 数据集\n",
    "本节使用tf.data.Dataset API构建管道，以便为模型提供数据。 tf.data.Dataset API用于从简单，可重复使用的部分构建高性能，复杂的输入管道，这些部分将为模型的培训或评估循环提供支持。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**创建源数据集**\n",
    "使用其中一个工厂函数（如Dataset.from_tensors，Dataset.from_tensor_slices）或使用从TextLineDataset或TFRecordDataset等文件读取的对象创建源数据集。 有关详细信息，请参阅TensorFlow数据集指南。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/tmp/tmpvl0kyn0w\n"
     ]
    }
   ],
   "source": [
    "# 从列表中获取tensor\n",
    "ds_tensors = tf.data.Dataset.from_tensor_slices([6,5,4,3,2,1])\n",
    "# 创建csv文件\n",
    "import tempfile\n",
    "_, filename = tempfile.mkstemp()\n",
    "print(filename)\n",
    "\n",
    "with open(filename, 'w') as f:\n",
    "    f.write(\"\"\"Line 1\n",
    "Line 2\n",
    "Line 3\"\"\")\n",
    "# 获取TextLineDataset数据集实例\n",
    "ds_file = tf.data.TextLineDataset(filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**应用转换**\n",
    "\n",
    "使用map，batch和shuffle等转换函数将转换应用于数据集记录。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "ds_tensors = ds_tensors.map(tf.square).shuffle(2).batch(2)\n",
    "ds_file = ds_file.batch(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**迭代**\n",
    "\n",
    "tf.data.Dataset对象支持迭代循环记录："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ds_tensors中的元素：\n",
      "tf.Tensor([36 25], shape=(2,), dtype=int32)\n",
      "tf.Tensor([16  9], shape=(2,), dtype=int32)\n",
      "tf.Tensor([4 1], shape=(2,), dtype=int32)\n",
      "\n",
      "ds_file中的元素：\n",
      "tf.Tensor([b'Line 1' b'Line 2'], shape=(2,), dtype=string)\n",
      "tf.Tensor([b'Line 3'], shape=(1,), dtype=string)\n"
     ]
    }
   ],
   "source": [
    "print('ds_tensors中的元素：')\n",
    "for x in ds_tensors:\n",
    "    print(x)\n",
    "# 从文件中读取的对象创建的数据源\n",
    "print('\\nds_file中的元素：')\n",
    "for x in ds_file:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
